import { ParameterObjectType, RENDERORDER } from '@amcax/base';
import { ctx2 } from '@app-cad/module';
import { Vector2tuple, Vector3 } from 'three-legacy';
import { AnnotationType, DiameterAttrs } from './types';
import {
  calculatePoint,
  getDotProduct,
  getSymmetricPoint,
} from '@app-cad/common/utils';
import DimBase from './DimBase';

export class DimDiameterTool extends DimBase {
  private center: Vector3; // 本地坐标
  private radius: number;
  private startPLcoal: Vector3;
  private endPLcoal: Vector3;
  private relPos: Vector2tuple[];
  private isOutCircle: boolean;
  private curveType: string;
  constructor(attrs: DiameterAttrs) {
    super();
    this.setUserData({ type: AnnotationType.RadiusAnno });
    this.init(attrs);
  }
  init(attrs: DiameterAttrs) {
    this.updateDisableIfCurvesFixed(attrs.curveIds);
    this.setDimInfo(attrs);
    const startPoint = this.getCalPoints(this.mouseXY);
    const endPoint = getSymmetricPoint(startPoint, this.center);
    // 转换成世界坐标
    // 设置箭头
    this.createArrow([startPoint, endPoint]); // 设置箭头
    // 设置线
    this.createUpdateLines();
    this.setCircle();
    this.userData.points = this.getPosLv();
    this.setRenderOrder(RENDERORDER.LINE - 1);
    this.createUpdateLabel(
      attrs,
      this.mouseXY,
      this.radius,
      ParameterObjectType.Length,
      2,
      'Φ',
    );
    this.setNormalColor();
  }
  createUpdateLines(isOutCircle = null) {
    let vertexs = [this.endPLcoal, this.mouseXY, this.startPLcoal];
    const flag = isOutCircle === null ? this.outCircle() : isOutCircle;
    if (flag) {
      const [p2, p3] = this.extendLine(
        [this.mouseXY, this.startPLcoal],
        'minus',
      );
      vertexs = [this.startPLcoal, p2, p3];
      this.createUpdateLine('line1', vertexs);
      this.removeLine(['line2']);
    } else {
      const [p1, p2] = this.extendLine(
        [this.mouseXY, this.startPLcoal],
        'minus',
      );
      this.createUpdateLine('line1', [p1, p2, p2]);
      const [p3, p4] = this.extendLine([this.mouseXY, this.endPLcoal], 'minus');
      this.createUpdateLine('line2', [p3, p4, p4]);
    }
  }
  setCircle() {
    if (this.curveType === 'ArcOfCircle') {
      const params = this.getArcVertexs({
        x: this.center.x,
        y: this.center.y,
        radius: this.radius,
        startAngle: 0,
        endAngle: Math.PI * 2,
        clockWise: true,
      });
      this.createUpdateLine('arcLine', params, {
        dashed: true,
      });
      this.lines.arcLine?.setRenderOrder(1);
    }
  }
  outCircle() {
    const raduis = this.radius;
    return this.mouseXY.distanceTo(this.center) > raduis;
  }
  zoomUpdate() {
    if (this.isOutCircle === undefined) {
      this.isOutCircle = this.outCircle();
    }
    if (this.startPLcoal) {
      if (!this.isOutCircle) {
        this.createArrow([this.startPLcoal, this.endPLcoal]);
      }
      this.createUpdateLines(this.isOutCircle); // 设置线
      this.setCircle(); // 设置圆
      ctx2.viewer.requestRender();
    }
  }
  update(attrs: DiameterAttrs) {
    this.setDimInfo(attrs);
    this.mouseXY = attrs.labelPos || this.getCalPointsByPos(this.relPos);
    const startPoint = this.getCalPoints(this.mouseXY);
    if (this.lines.line1) {
      const endPoint = getSymmetricPoint(startPoint, this.center);
      this.createArrow([startPoint, endPoint]); // 设置箭头
      this.createUpdateLines(); // 设置线
      this.setCircle(); // 设置圆
      this.createUpdateLabel(
        attrs,
        this.mouseXY,
        this.radius,
        ParameterObjectType.Length,
        2,
      );
    }
    this.isOutCircle = this.outCircle();
  }
  createArrow([startPoint, endPoint]) {
    if (this.outCircle()) {
      this.updateArrow(
        [startPoint],
        [new Vector3().subVectors(this.mouseXY, startPoint)],
        'vector',
      );
      this.startPLcoal = startPoint;
      this.endPLcoal = null;
    } else {
      this.updateArrow([startPoint, endPoint]);
      this.startPLcoal = startPoint;
      this.endPLcoal = endPoint;
    }
  }
  // 获取点
  getCalPoints(mouseWV: Vector3) {
    const vec = new Vector3().subVectors(this.center, mouseWV).normalize();
    // 垂直向量
    const sign = getDotProduct(this.center, mouseWV, vec) >= 0 ? 1 : -1;
    const point = calculatePoint(vec, this.radius * sign, this.center);
    return point;
  }
  getPosLv(): Vector2tuple[] {
    this.userData.points = this.relPos = [
      [this.mouseXY.x - this.center.x, this.mouseXY.y - this.center.y],
      [1, 0], // 1 直径
    ];
    return this.relPos;
  }
  // 根据相对位置计算点
  getCalPointsByPos([relPos]: Vector2tuple[]) {
    return new Vector3(this.center.x + relPos[0], this.center.y + relPos[1], 0);
  }
  getVal() {
    return this.dimLabel.getText();
  }
  // 设置尺寸信息
  setDimInfo(attrs: DiameterAttrs) {
    this.setUserData({
      objects: attrs.curveIds,
      type: attrs.dimConstraint,
    });
    if (attrs.center) {
      this.center = attrs.center;
    }
    if (attrs.radius) {
      this.radius = attrs.radius;
    }
    if (attrs.curveType) {
      this.curveType = attrs.curveType;
    }
    if (attrs.labelPos) {
      this.mouseXY = attrs.labelPos;
    } else {
      if (attrs.relPos?.length > 0) {
        this.relPos = attrs.relPos;
      } else {
        const xy = this.radius + this.defaultDimPos(50);
        this.relPos = this.relPos || [[xy, xy]];
      }
      this.mouseXY = this.getCalPointsByPos(this.relPos);
    }
  }
  defaultMouseXY() {
    const xy = this.radius + this.defaultDimPos(50);
    this.relPos = [[xy, xy]];
    this.mouseXY = this.getCalPointsByPos(this.relPos);
  }
}
